<?php

/*
 * CopyRight  : (C)2012-2099 HaoTeam Inc.
 * Document   : WechatAppService.php
 * Created on : 2021-2-18 10:15:15
 * Author     : Tiger <1192851302@qq.com>
 * Description: This is NOT a freeware, use is subject to license terms.
 *              这即使是一个免费软件,使用时也请遵守许可证条款,得到当时人书面许可.
 *              未经书面许可,不得翻版,翻版必究;版权归属 HaoTeam Inc;
 */

namespace haoteam\service;

use think\facade\View;
use think\facade\Session;
use think\facade\Db;

/**
 * 
 * Class WechatAppService
 * Tiger <1192851302@qq.com> 2021-2-18 10:15:15
 */
class WechatAppService {

    public $addonInfo = [];
    public $addon;
    public $mid;

    public function __construct($type) {
        try {
            $this->addon = input('addon') ?: request()->addon();
        } catch (\Exception $exc) {
            
        }
        if ($this->addon) {
            $this->addonInfo = $this->getAppByFile($this->addon, $type);
            Session::set('WechatAppInfo', $this->addonInfo);
        } else {
            $this->addonInfo = Session::get('WechatAppInfo') ?: null;
        }
        try {
            $this->mid = input('mid') ?: request()->mid();
        } catch (\Exception $exc) {
            
        }

        if ($this->mid) {
            Session::set('WechatAppMid', $this->mid);
        } else {
            $this->mid = Session::get('WechatAppMid') ?: null;
        }
    }

    /**
     * 快速实例化模型
     * @author Tiger <1192851302@qq.com>
     * @param string $type Description
     * @param bool $singleton 是否单例
     * @return static
     */
    public static function instance($type = 'miniapp', $singleton = true) {
        $name = static::class;
        if (isset($GLOBALS['model'][$name]) and is_object($GLOBALS['model'][$name]) and $singleton) {
            return $GLOBALS['model'][$name];
        } else {
            $GLOBALS['model'][$name] = new static($type);
            return $GLOBALS['model'][$name];
        }
    }

    /**
     * 获取指定类型应用列表
     * @author Tiger <1192851302@qq.com>
     * @param type $type 应用类型
     * @return type
     */
    public function getAppList($type = 'miniapp') {
        $str = opendir(root_path() . $type);

        if ($str === false) {
            return false;
        }
        $list = [];
        while (($appName = readdir($str)) !== false) {
            if ($appName != "." && $appName != "..") {
                $list[] = $this->getAppByFile($appName, $type);
            }
        }
        closedir($str);
        return $list;
    }

    /**
     * 读取应用配置文件
     * @author Tiger <1192851302@qq.com>
     * @param type $appName 应用标识
     * @param type $type    应用类型
     * @return boolean
     */
    private function getAppByFile($appName, $type = 'miniapp') {
        if ($appName == null) {
            return $this->addonInfo;
        }
        $path = root_path() . $type . '/' . $appName . '/' . 'Config.php';
        if (is_file($path)) {
            $appInfo = include_once $path;
            if (empty($appInfo)) {
                return false;
            }
            if ($appInfo['addon'] != $appName) {
                return false;
            }
            $appInfo['type'] = $type;
            return $appInfo;
        } else {
            return false;
        }
    }

    /**
     * 获取文件中Mysql
     * @author Tiger <1192851302@qq.com>
     * @param type $type    应用类型
     * @param type $appName 应用标识
     * @return boolean
     */
    private function getMysqlByFile($file) {
        $path = root_path() . $this->addonInfo['type'] . '/' . $this->addonInfo['addon'] . '/' . $file;
        if (is_file($path) === false) {
            return false;
        }
        $sql = explode(";\n", str_replace("\r", "\n", file_get_contents($path)));
        $orginal = 'ht_';
        $prefix = \think\facade\Config::get('database.prefix');
        $data = str_replace("{$orginal}", "{$prefix}", $sql);
        $datas = [];
        foreach ($data as $item) {
            $item = trim($item);
            if (empty($item)) {
                continue;
            }
            $datas[] = $item;
        }
        return $datas;
    }

    /**
     * 执行安装/更新Mysql
     * @author Tiger <1192851302@qq.com>
     * @param type $file    Mysql文件名称
     * @return boolean
     */
    public function execute_sql($file) {
        $sql = $this->getMysqlByFile($file);
        if ($sql === false) {
            return false;
        }
        foreach ($sql as $value) {
            if (in_array(substr($value, 0, 12), ['CREATE TABLE']) == false) {
                continue;
            }
            $name = '';
            preg_match('|EXISTS `(.*?)`|', $value, $outValue1);
            preg_match('|TABLE `(.*?)`|', $value, $outValue2);
            if (isset($outValue1[1]) && !empty($outValue1[1])) {
                $name = $outValue1[1];
            }
            if (isset($outValue2[1]) && !empty($outValue2[1])) {
                $name = $outValue2[1];
            }
            if (empty($name)) {
                exception($name . ' SQL语句有误，获取不到表名');
            }
            if (Db::query("SHOW TABLES LIKE '{$name}'")) {
                exception($name . '表，已经存在');
            }
            Db::execute($value);
        }
        return true;
    }

    /**
     * 执行卸载Mysql
     * @author Tiger <1192851302@qq.com>
     * @param type $file    Mysql文件名称
     * @return boolean
     */
    public function execute_uninstall_sql($file) {
        $sql = $this->getMysqlByFile($file);
        if ($sql === false) {
            return false;
        }
        foreach ($sql as $value) {
            if (in_array(substr($value, 0, 12), ['CREATE TABLE']) == false) {
                continue;
            }
            $name = '';
            preg_match('|EXISTS `(.*?)`|', $value, $outValue1);
            preg_match('|TABLE `(.*?)`|', $value, $outValue2);
            if (isset($outValue1[1]) && !empty($outValue1[1])) {
                $name = $outValue1[1];
            }
            if (isset($outValue2[1]) && !empty($outValue2[1])) {
                $name = $outValue2[1];
            }
            if (empty($name)) {
                exception($name . ' SQL语句有误，获取不到表名');
            }
            if (Db::query("SHOW TABLES LIKE '{$name}'")) {
                if (Db::execute("DROP TABLE `{$name}`;") === false) {
                    exception('删除' . $name . '表失败');
                }
            }
        }
        return true;
    }

    /**
     * 加载模板输出
     * @author Tiger <1192851302@qq.com>
     * @param type $template
     * @param type $vars
     * @param type $config
     * @return type
     */
    public function fetch($template = '', $vars = [], $config = []) {
        [$controller, $action] = explode('_', input('nodes'));
        View::config(array_merge([
            'view_path' => root_path() . 'miniapp/' . $this->addonInfo['addon'] . '/view/',
            'tpl_replace_string' => [
                '__STATIC__' => '/static/admin/',
                '__ADDONSTATIC__' => root_path() . 'miniapp/' . $this->addonInfo['addon'] . '/static/'
            ]
                        ], $config));
        return View::fetch($template ?: ucfirst($controller) . '/' . $action, $vars);
    }

    /**
     * 绑定菜单
     * @author Tiger <1192851302@qq.com>
     * @return array
     */
    public function bindMeun() {
        return [
            [
                'name' => '系统功能',
                'url' => '#',
                'child' => [
                    [
                        'name' => '基础功能',
                        'url' => '#',
                        'child' => [
                            [
                                'name' => '应用设置',
                                'icon' => 'layui-icon-set',
                                'url' => url('/wechat/app/config')->domain(true)
                            ],
                            [
                                'name' => '粉丝列表',
                                'icon' => 'layui-icon-user',
                                'url' => url('/wechat/app/fans')->domain(true)
                            ]
                        ]
                    ]
                ]
            ],
            [
                'name' => '应用功能',
                'url' => '#',
                'child' => $this->bindMenuUrl($this->addonInfo['menu'])
            ]
        ];
    }

    /**
     * 生成应用菜单链接
     * @author Tiger <1192851302@qq.com>
     * @param array $menus Description
     * @return array
     */
    private function bindMenuUrl($menus) {
        foreach ($menus as $key => &$item) {
            if (isset($item['child'])) {
                $item['child'] = $this->bindMenuUrl($item['child']);
                continue;
            }
            $item['url'] = addonUrl($item['url']);
        }
        return $menus;
    }

    /**
     * 输出应用
     * @author Tiger <1192851302@qq.com>
     * @param type $nodes
     * @param type $addon
     * @return type
     */
    public function run($nodes, $addon = null) {
        if ($addon === null) {
            $addon = request()->addon();
        }
        if (file_exists($commonFile = root_path() . 'miniapp/' . $addon . '/Common.php')) {//引入公共办法
            include_once $commonFile;
        }
        //解析路由
        [$controller, $action] = explode('_', $nodes);
        include_once root_path() . 'miniapp/' . $addon . '/controller/' . ucfirst($controller) . '.php';
        $class = '\miniapp\\' . $addon . '\controller\\' . ucfirst($controller);
        if (class_exists($class)) {
            $model = new $class;
            if (method_exists($model, $action) == false) {
                abort(500, lang($action . '方法不存在'));
            }
            return call_user_func_array([$model, $action], []);
        } else {
            abort(500, lang($class . '不存在'));
        }
    }

}
